/*
 * nume: fingerprint.h
 * autor: Tiberiu
 * descriere: modulul de indexare locala
 *     (pe calculatorul clientului) a fisierelor clientului
 *
 * Modificari
 *   26 Mai 2007 - ALexandru
 *      - am adaugat clasa CompareFingerPrint pentru
 *        a compara doua amprente
 *      - am adaugat functia membru 'clone' ce returneaza
 *        o copie a amprentei
 *   24 Mai 2007 - Alexandru
 *      - am imbunatatit comentariile,
 *      - corectat greseli in clasa
 *   24 Mai 2007 - Tiberiu
 *      - prima versiune
 */


#ifndef FINGERPRINT_H__
#define FINGERPRINT_H__

#include "sha2.h"
#include <functional>
#include <QtCore>

class FingerPrint {
public:
	static void hash(QFile& file,
                       FingerPrint* finger,
                       std::vector<FingerPrint>* fingers,
                       qint64 *size);
    /*
     * calculeaza hash-ului unui text, si intoarce
     * valoare calculata in 'finger'
     */
    static void hash(const quint8 *text, int length,
                     FingerPrint* finger);
	/*
     * calculeaza hash-ului unui fisier, si intoarce
     * valoare calculata in 'finger'
     */
    static void hash(QFile& file,FingerPrint* finger);
                     
    /*
     * Functii care calculeaza hash-ul pentru
     * fisierul asociat obiectului FingerPrint
     * Pentru a nu incarca in memorie tot fisierul,
     * se va calcula hash-ul pe bucati
     */
    void init();
    void append(const quint8 *text, int length);
    void end();

    /*
     * returneaza adevarat in caz de egalitate
     * dintre obiectul curent si 'finger'
     */
    bool equals(const FingerPrint* finger) const;

    /*
     * intoarce o copie a acestui FingerPrint
     * apelantul trebuie sa dezaloce memoria pentru
     * amprenta curenta
     */
    FingerPrint* clone() const;

    /*
     * initializeaza acest FingerPrint cu suma
     * tuturor amprentelor din vectorul primit ca
     * parametru
     */
    void sum(const std::vector<FingerPrint>& fingers);

    quint8 signature(int i) const {
        return signature_[i];
    }

    void set_signature(int i, quint8 value) {
        signature_[i] = value;
    }

    static int signature_size() {
        return 16;
    }

private:
    union {
        quint8 signature_[16];
        quint32 h[8];
    };

    sha256_ctx* pctx;
};

class CompareFingerPrintPointer {
public:
#if 0
    // intoarce 'true' daca 'finger1' este mai mic decat 'finger2'
    bool operator () (const FingerPrint& finger1,
                      const FingerPrint& finger2) const {
        for (int i = 0; i < 16; ++i) {
            if (finger1.signature_[i] < finger2.signature_[i])
                return true;
            if (finger1.signature_[i] > finger2.signature_[i])
                return false;
        }
        return false;
    }
#endif

    // intoarce 'true' daca 'finger1' este mai mic decat 'finger2'
    bool operator () (const FingerPrint* finger1,
                      const FingerPrint* finger2) const {
        for (int i = 0; i < 16; ++i) {
            if (finger1->signature(i) < finger2->signature(i))
                return true;
            if (finger1->signature(i) > finger2->signature(i))
                return false;
        }
        return false;
    }
};

#endif  // FINGERPRINT_H__
